﻿using System;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Numbers;
using Numbers.Arithmatic;
using Microsoft.Silverlight.Testing;

namespace t_Numbers
{
    [TestClass]
    public class t_TagEfficiency
    {
        [TestMethod]
        public void TestCreation()
        {
            TagEfficiency te = new TagEfficiency();

            Assert.AreEqual(0.0, te.eff_b, "should init b-tagging eff to zero");
            Assert.AreEqual(0.0, te.eff_c, "Should init c-tagging eff to zero");
            Assert.AreEqual(0.0, te.eff_l, "Should init the -ltagging eff to zero");
        }

        [TestMethod]
        public void TestSetting()
        {
            TagEfficiency te = new TagEfficiency();

            te.eff_b = 0.1;
            te.eff_c = 0.2;
            te.eff_l = 0.3;

            Assert.AreEqual(0.1, te.eff_b, "should init b-tagging eff to zero");
            Assert.AreEqual(0.2, te.eff_c, "Should init c-tagging eff to zero");
            Assert.AreEqual(0.3, te.eff_l, "Should init the -ltagging eff to zero");
        }

        [TestMethod]
        public void TestOverSetting()
        {
            TagEfficiency te = new TagEfficiency();

            te.eff_b = te.eff_c = te.eff_l = 1.5;
            Assert.AreEqual(1.0, te.eff_b, "Expecting max of 1 for b");
            Assert.AreEqual(1.0, te.eff_c, "Expecting max of 1 for c");
            Assert.AreEqual(1.0, te.eff_l, "Expecting max of 1 for l");

            te.eff_b = te.eff_c = te.eff_l = -4.0;
            Assert.AreEqual(0.0, te.eff_b, "Expecting min of 0 for b");
            Assert.AreEqual(0.0, te.eff_c, "Expecting min of 0 for c");
            Assert.AreEqual(0.0, te.eff_l, "Expecting min of 0 for l");
        }

        [TestMethod]
        public void TestMultiply()
        {
            TagEfficiency result = new TagEfficiency();
            Alpha a = new Alpha();
            TagEfficiency source = new TagEfficiency();

            TagEfficiency.Multiply(result, a, source);

            Assert.AreEqual(0.0, result.eff_b, "Expected eff b for the result would be zero before we started!");
            source.eff_b = 0.5;
            Assert.AreEqual(0.5, source.eff_b, "eff_b not set right!");
            Assert.AreEqual(0.0, result.eff_b, "Expected eff b for the result would be zero still!");
            a.alpha_b = 2.0;
            Assert.AreEqual(0.0, result.eff_b, "eff_b shouldn't be altered when we changed alpha as everything else is fixed");
            Assert.AreEqual(0.0, a.alpha_b, "The alpha b should not have been allowed to change from 0.0!");
            result.eff_b = 1.0;
            Assert.AreEqual(1.0, result.eff_b, "eff_b should be 1");
            Assert.AreEqual(2.0, a.alpha_b, "Expecting alpha b to be 2.0");

            source.eff_b = 0.5;
            source.eff_c = 0.4;
            source.eff_l = 0.25;

            result.eff_l = 1.0;
            result.eff_c = 0.8;
            result.eff_b = 0.6;

            Assert.AreEqual(1.2, a.alpha_b, "alpha b have been updated!");
            Assert.AreEqual(2.0, a.alpha_c, "alpha c have been updated");
            Assert.AreEqual(4.0, a.alpha_l, "alpha light have been updated!");
        }

        [TestMethod]
        public void TestMultiply2()
        {
            TagEfficiency result = new TagEfficiency();
            Alpha a = new Alpha();
            TagEfficiency source1 = new TagEfficiency();
            TagEfficiency source2 = new TagEfficiency();

            TagEfficiency.Multiply(result, a, source1, source2);

            Assert.AreEqual(1.0, a.alpha_b, "Expected initial alpha b to be one");
            source1.eff_b = 0.5;
            Assert.AreEqual(0.0, result.eff_b, "Expected zero for eff_b since source 2 is still zero");
            source2.eff_b = 1.0;
            Assert.AreEqual(0.0, result.eff_b, "eff_b not set right!");
            a.alpha_b = 2.0;
            Assert.AreEqual(0.0, result.eff_b, "eff_b shuldn't change when alpha is changed");
            Assert.AreEqual(0.0, a.alpha_b, "alpha_b should have remained zero!");
            result.eff_b = 1.0;
            Assert.AreEqual(1.0, result.eff_b, "eff_b didn't see the alpha");
            Assert.AreEqual(2.0, a.alpha_b, "alpha_b should have been set to make it all work");

            source1.eff_c = 0.4;
            source1.eff_l = 0.3;

            Assert.AreEqual(0.0, result.eff_c, "eff_c should be zero still source 2 is set");
            Assert.AreEqual(0.0, result.eff_l, "eff_l should be zero still source 2 is set");

            source2.eff_c = 1.0;
            source2.eff_l = 1.0;

            Assert.AreEqual(0.0, result.eff_c, "eff_c should be zero still source 2 is set");
            Assert.AreEqual(0.0, result.eff_l, "eff_l should be zero still source 2 is set");

            result.eff_l = 0.9;
            result.eff_c = 0.8;
            result.eff_b = 0.5;

            Assert.AreEqual(1.0, a.alpha_b, "alpha b should not change!");
            Assert.AreEqual(2.0, a.alpha_c, "alpha c should not change");
            Assert.AreEqual(3.0, a.alpha_l, "alpha light should not change!");
        }

        [TestMethod]
        public void TestNoifyPropertyChanged()
        {
            TagEfficiency result = new TagEfficiency();
            int count = 0;
            string lastChange = "";
            result.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler((o, e) => { count += 1; lastChange = e.PropertyName; });

            result.eff_b = 0.5;
            Assert.AreEqual("eff_b", lastChange, "The proper change event didn't fire for eff_b");
            result.eff_c = 0.5;
            Assert.AreEqual("eff_c", lastChange, "The proper change event didn't fire for eff_c");
            result.eff_l = 0.5;
            Assert.AreEqual("eff_l", lastChange, "The proper change event didn't fire for eff_l");

            count = 0;
            result.eff_b = 0.5;
            result.eff_c = 0.5;
            result.eff_l = 0.5;

            Assert.AreEqual(0, count, "Setting to the same value should not have caused a change!");

            Alpha a = new Alpha();
            TagEfficiency source = new TagEfficiency() {eff_b = 1.0, eff_c = 1.0, eff_l = 1.0};
            TagEfficiency.Multiply(result, a, source);
            count = 0;

            source.eff_b = 0.5;
            Assert.AreEqual(0, count, "No change event should have fired - result shoudl be fixed");
            source.eff_c = 0.5;
            Assert.AreEqual(0, count, "No change event should have fired - result shoudl be fixed");
            source.eff_l = 0.5;
            Assert.AreEqual(0, count, "No change event should have fired - result shoudl be fixed");

            a.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler((o, e) => { count += 1; lastChange = e.PropertyName; });

            source.eff_b = 1.0;
            Assert.AreEqual("alpha_b", lastChange, "Expected alpha_b as the change event!");
            source.eff_c = 1.0;
            Assert.AreEqual("alpha_c", lastChange, "Expected alpha_c as the change event!");
            source.eff_l = 1.0;
            Assert.AreEqual("alpha_l", lastChange, "Expected alpha_l as the change event!");
            Assert.AreEqual(3, count, "Expected only three changes!");
        }

        [TestMethod]
        public void TestCollection()
        {
            TagEfficiency eff = new TagEfficiency();

            Assert.IsNotNull(eff.EffArray, "EffArray is null - bad!");
            Assert.AreEqual(3, eff.EffArray.Count, "EffArray should be three!");

            Assert.AreEqual("b", eff.EffArray[2].Name, "eff b name not right 1");
            Assert.AreEqual("c", eff.EffArray[1].Name, "eff c name not right 1");
            Assert.AreEqual("l", eff.EffArray[0].Name, "eff l name not right 1");

            Assert.AreEqual(0.0, eff.EffArray[2].Value, "eff b not right 1");
            Assert.AreEqual(0.0, eff.EffArray[1].Value, "eff c not right 1");
            Assert.AreEqual(0.0, eff.EffArray[0].Value, "eff l not right 1");

            eff.eff_b = 0.1;
            eff.eff_c = 0.2;
            eff.eff_l = 0.3;

            Assert.AreEqual(0.1, eff.EffArray[2].Value, "eff b not right 2");
            Assert.AreEqual(0.2, eff.EffArray[1].Value, "eff c not right 2");
            Assert.AreEqual(0.3, eff.EffArray[0].Value, "eff l not right 2");
        }
    }
}